﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Linq;
using Styx;
using Styx.Helpers;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.POI;
using Styx.CommonBot.Profiles;
using Styx.CommonBot.Inventory;
using Styx.MemoryManagement;
using Styx.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals.World;
using Styx.Plugins;
using System.Windows.Forms;
using Tripper.Navigation;

namespace BuddyManager
{
    public partial class BuddyManager
    {
        public static Executor executor;

        private static bool IsNotSafe()
        {
            ObjectManager.Update();
            return (StyxWoW.Me.CurrentHealth < 2 || StyxWoW.Me.IsInInstance || Styx.WoWInternals.Battlegrounds.IsInsideBattleground || StyxWoW.Me.Combat || StyxWoW.Me.IsActuallyInCombat || !StyxWoW.IsInWorld || !StyxWoW.IsInGame || (new List<PoiType> { PoiType.Harvest, PoiType.Buy, PoiType.Corpse, PoiType.Kill, PoiType.Loot, PoiType.Skin, PoiType.Train }.Equals(BotPoi.Current.Type)));
        }

        private static bool WasLastTask(DateTime _BaseStartTime, int LastTaskIndex)
        {
            return (uSettings.LogOutAfter && ((DateTime.Now - _BaseStartTime).TotalMinutes >= TaskList[LastTaskIndex].SwitchInt && uSettings.TasksCompleted >= TaskList.Count -1));
        }

        public void SwitchTaskChecksUpdates()
        {
            uSettings.TasksCompleted++;
            LastTaskIndex = CurrentTaskIndex;
            CurrentProfileIndex = 0;
            _InternalNodeCount = 0;
            if (uSettings.Randomize)
            {
                Log("Randomizing next task.");
                while (CurrentTaskIndex == LastTaskIndex)
                {
                    CurrentTaskIndex = RanNum(0, TaskList.Count - 1);
                }
                Log(string.Format("Chosen task: {0}", (CurrentTaskIndex)));
            }
            else
                CurrentTaskIndex++;
            Log(string.Format("Task {0} completed", LastTaskIndex.ToString()));
            TotalRunningTime();

            if (WasLastTask(_BaseStartTime, LastTaskIndex))
            {
                Log("All tasks have been completed, and BM is not set to loop.");
                Log("Sending ForceQuit() to Wow.exe");
                InactivityDetector.ForceLogout(true);
                return;
            }
            if (!uSettings.Randomize && CurrentTaskIndex > TaskList.Count - 1) CurrentTaskIndex = 0;

        }

        private void RepairSellMail(bool vendor, bool mail)
        {
            uint VendorEntry = 0;
            WoWPoint VendorLoc = new WoWPoint();
            WoWPoint MailboxLoc = new WoWPoint();
            WoWUnit _Vendor;
            if (Me.IsHorde)
            {
                VendorEntry = 3319;
                VendorLoc = new WoWPoint(1584.327, -4318.02, 21.18613);
                MailboxLoc = new WoWPoint(1551.957, -4359.154, 17.89191);
            }
            if (Me.IsAlliance)
            {
                VendorEntry = 54321;
                VendorLoc = new WoWPoint(0, 0, 0);
                MailboxLoc = new WoWPoint(0, 0, 0);
            }
            if (vendor)
            {
                while (VendorLoc.Distance(Me.Location) > 1)
                {
                    if (!Flightor.MountHelper.Mounted && Flightor.MountHelper.CanMount)
                    {
                        Flightor.MountHelper.MountUp();
                        StyxWoW.SleepForLagDuration();
                        Thread.Sleep(500);
                        while (Me.IsCasting) { Thread.Sleep(100); }
                    }
                    Log("Mounted and flying to Vendor!");
                    Flightor.MoveTo(VendorLoc);
                    Thread.Sleep(250);
                }

                Log("Dismounting.");
                //while (Me.IsFlying) { WoWMovement.Move(WoWMovement.MovementDirection.Descend, TimeSpan.FromSeconds(1)); }
                //Log("Landed.");
                Flightor.MountHelper.Dismount();
                StyxWoW.SleepForLagDuration();
                WoWMovement.MoveStop(WoWMovement.MovementDirection.All);
                Navigator.PlayerMover.MoveStop();

                Thread.Sleep(RanNum(500, 1500));
                foreach (WoWUnit unit in ObjectManager.GetObjectsOfType<WoWUnit>().Where(o => o.Entry == VendorEntry))
                {
                    while (unit.Location.Distance(Me.Location) > unit.InteractRange)
                    {
                        Navigator.MoveTo(unit.Location);
                        Log(string.Format("Moving towards: {0}.", unit.Name));
                        Thread.Sleep(RanNum(1000, 3000));
                        _Vendor = unit;
                    }
                    WoWMovement.MoveStop();
                    Navigator.PlayerMover.MoveStop();
                    unit.Interact();
                    break;
                }
                StyxWoW.SleepForLagDuration();
            }
            if (Me.CurrentTarget != null)
            {
                if (vendor)
                {
                    for (int i = 0; i < 3; i++)
                    {
                        Vendors.RepairAllItems(); Thread.Sleep(RanNum(500, 3000));
                    }
                }
                if (Me.Auras.ContainsKey("Herbouflage")) { Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/cancelaura Herbouflage")); }
                if (Me.ActiveAuras.ContainsKey("Herbouflage")) { Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/cancelaura Herbouflage")); }
                if (vendor)
                {
                    for (int i = 0; i < 3; i++)
                    {
                        Vendors.SellAllItems(); Thread.Sleep(RanNum(500, 3000));
                    }
                }
                if (Me.Auras.ContainsKey("Herbouflage")) { Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/cancelaura Herbouflage")); }
                if (Me.ActiveAuras.ContainsKey("Herbouflage")) { Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/cancelaura Herbouflage")); }
            }
            if (mail)
            {
                ForceMailManager.ReloadProtectedItems();
                ForceMailManager.Add("Volatile Air");
                ForceMailManager.Add("Volatile Earth");
                ForceMailManager.Add("Volatile Water");
                ForceMailManager.Add("Volatile Fire");
                ForceMailManager.Add("Volatile Life");
                ForceMailManager.Add("Twilight Jasmine");
                ForceMailManager.Add("Whiptail");
                ForceMailManager.Add("Cinderbloom");
                ForceMailManager.Add("Heartblossom");
                ForceMailManager.Add("Azshara's Veil");
                ForceMailManager.Add("Stormvine");
                InventoryManager.GetItemsToMail();
                if (InventoryManager.HaveItemsToMail)
                {
                    if (!String.IsNullOrEmpty(CharacterSettings.Instance.MailRecipient))
                    {
                        bool Foundbox = false;
                        ObjectManager.Update();
                        Log("You have items to mail, and a Recipient set!");
                        var Mailboxes = ObjectManager.GetObjectsOfType<WoWGameObject>().Where(o => Navigator.CanNavigateFully(Me.Location, o.Location) && o.SubType == WoWGameObjectType.Mailbox);
                        foreach (WoWGameObject Mailbox in ObjectManager.GetObjectsOfType<WoWGameObject>().Where(o => Navigator.CanNavigateFully(Me.Location, o.Location) && o.SubType == WoWGameObjectType.Mailbox && o.Entry != 206725))
                        {
                            Log("Found a Mailbox (Auto).  Moving to it.", null);
                            while (Mailbox.Location.Distance(Me.Location) > Mailbox.InteractRange) { Navigator.MoveTo(Mailbox.Location); }
                            Thread.Sleep(500);
                            Navigator.PlayerMover.MoveStop();
                            WoWMovement.MoveStop(WoWMovement.MovementDirection.All);
                            Thread.Sleep(1000);
                            Mailbox.Interact();
                            Thread.Sleep(500);
                            Mailbox.Interact();
                            StyxWoW.SleepForLagDuration();
                            Log("Mailing Items!");
                            int i = 0;
                            while (InventoryManager.HaveItemsToMail)
                            {
                                Thread.Sleep(RanNum(2000, 5000));

                                Vendors.MailAllItems();
                                i++;
                                if (i > 10) break;
                            }
                            if (Me.Auras.ContainsKey("Herbouflage")) { Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/cancelaura Herbouflage")); }
                            if (Me.ActiveAuras.ContainsKey("Herbouflage")) { Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/cancelaura Herbouflage")); }
                            StyxWoW.SleepForLagDuration();
                            Foundbox = true;
                            break;
                        }
                        if (!Foundbox)
                        {
                            Log("Couldn't find a mailbox automatically.  Using back-up.");
                            while (MailboxLoc.Distance(Me.Location) > 5)
                            {
                                if (!Flightor.MountHelper.Mounted && Flightor.MountHelper.CanMount)
                                {
                                    Flightor.MountHelper.MountUp();
                                    StyxWoW.SleepForLagDuration();
                                    Thread.Sleep(500);
                                    while (Me.IsCasting) { Thread.Sleep(100); }
                                }
                                Log("Mounted and flying to Mailbox!");
                                Flightor.MoveTo(MailboxLoc);
                                Thread.Sleep(250);
                            }
                            Log("Dismounting.");
                            Flightor.MountHelper.Dismount();
                            StyxWoW.SleepForLagDuration();
                            WoWMovement.MoveStop(WoWMovement.MovementDirection.All);
                            Navigator.PlayerMover.MoveStop();

                            Thread.Sleep(RanNum(1500, 3000));
                            ObjectManager.Update();
                            Foundbox = true;

                        }
                        if (Foundbox)
                        {
                            while (VendorLoc.Distance(Me.Location) > 1)
                            {
                                Log("Walking back to Original Vendor Location.");
                                Thread.Sleep(250);
                                Navigator.MoveTo(VendorLoc);
                            }
                        }
                        if (!Foundbox) { Log("Didn't find a Mailbox to use.  Please head to TheBuddyForum and report this issue in the BuddyManager thread!!!"); }
                    }
                    else Log("You don't have a mail recipient set!");
                }
                else Log("Found no items to mail.");
            }

            while (VendorLoc.Distance(Me.Location) > 5)
            { Navigator.MoveTo(VendorLoc); Thread.Sleep(100); }

            NeedToRepairMailSell = false;
            ResetChanger();
            return;
        }

        private void MoveAfterPortal()
        {
            if (TaskList[CurrentTaskIndex].Zone == "Twilight Highlands")
            {
                if (Me.IsHorde)
                {
                    Thread.Sleep(5000);
                    Log("Moving Outside (Twilight Highlands/Horde).");
                    Stopwatch MovementTimer = new Stopwatch();
                    MovementTimer.Start();
                    Thread.Sleep(100); WoWMovement.Move(WoWMovement.MovementDirection.Forward, TimeSpan.FromSeconds(5)); MovementTimer.Reset();
                    Thread.Sleep(5000);
                    WoWMovement.MoveStop();
                    Navigator.PlayerMover.MoveStop();
                    DidUsePortal = false;
                    PulseChanger();
                    return;
                }
            }

            if (TaskList[CurrentTaskIndex].Zone == "Hyjal")
            {
                if (Me.IsAlliance)
                {
                    Thread.Sleep(5000);
                    while (!Me.Mounted && !IsNotSafe())
                    {
                        Flightor.MountHelper.MountUp();
                        Thread.Sleep(500);
                        while (Me.IsCasting) Thread.Sleep(100);
                    }
                    Log("Flying up a little to make sure GB2 will take control.");
                    WoWMovement.Move(WoWMovement.MovementDirection.JumpAscend);
                    Thread.Sleep(1000);
                    WoWMovement.MoveStop(WoWMovement.MovementDirection.JumpAscend);
                    WoWMovement.MoveStop(WoWMovement.MovementDirection.All);
                    WoWMovement.MoveStop();
                    DidUsePortal = false;
                    PulseChanger();
                    return;
                }
            }

            if (TaskList[CurrentTaskIndex].Zone == "Vashj'ir")
            {
                Thread.Sleep(5000);

                //---------------------------Potential Alliance--------------------------------
                //Alliance Upturned Ship
                if (Me.Location.Distance(new WoWPoint(-4444.841, 3810.633, -86.79523)) < 30)
                {
                    Log("Leaving Upturned Ship -Alliance");
                    while (Me.Location.Distance(new WoWPoint(-4444.841,3810.633,-86.79523)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-4444.841, 3810.633, -86.79523));
                        Thread.Sleep(250);
                    }
                    while (Me.Location.Distance(new WoWPoint(-4460.656,3799.523,-88.11741)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-4460.656, 3799.523, -88.11741));
                        Thread.Sleep(250);
                    }
                    while (Me.Location.Distance(new WoWPoint(-4448.351,3777.604,-99.1443)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-4448.351, 3777.604, -99.1443));
                        Thread.Sleep(250);
                    }
                }

                //Smuggler Scar
                if (Me.Location.Distance(new WoWPoint(-4563.4, 3470.16, -101.513)) < 30)
                {
                    Log("Leaving Smuggler Scar -Alliance");
                    while (Me.Location.Distance(new WoWPoint(-4650.891, 3562.462, -127.9466)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-4650.891, 3562.462, -127.9466));
                        Thread.Sleep(250);
                    }
                    while (Me.Location.Distance(new WoWPoint(-4670.238, 3577.063, -102.3758)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-4670.238, 3577.063, -102.3758));
                        Thread.Sleep(250);
                    }
                }

                //Silver Tide Hollow
                if (Me.Location.Distance(new WoWPoint(-6117.065, 4288.275, -348.8767)) < 30)
                {
                    Log("Leaving Silver Tide Hollow -Alliance");
                    while (Me.Location.Distance(new WoWPoint(-6001.027, 4232.159, -380.8471)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-6001.027, 4232.159, -380.8471));
                        Thread.Sleep(250);
                    }
                }

                //DarkBreak Cove
                if (Me.Location.Distance(new WoWPoint(-6884.06, 5963.37, -765.485)) < 30)
                {
                    Log("Leaving Darkbreak Cove -Alliance");
                    while (Me.Location.Distance(new WoWPoint(-6938.118, 5925.079, -768.1432)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-6938.118, 5925.079, -768.1432));
                        Thread.Sleep(250);
                    }
                    while (Me.Location.Distance(new WoWPoint(-6962.967, 5919.48, -794.3348)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-6962.967, 5919.48, -794.3348));
                        Thread.Sleep(250);
                    }
                    while (Me.Location.Distance(new WoWPoint(-7111.921, 5725.653, -830.3787)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-7111.921, 5725.653, -830.3787));
                        Thread.Sleep(250);
                    }
                    while (Me.Location.Distance(new WoWPoint(-7093.884, 5718.287, -664.8107)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-7093.884, 5718.287, -664.8107));
                        Thread.Sleep(250);
                    }
                }


                //---------------------Pretty Much Horde, I think --------------------------
                //Horde Ship
                if (Me.Location.Distance(new WoWPoint(-4611.241, 3974.056, -71.84396)) < 30)
                {
                    Log("Leaving Upturned Ship -Horde");
                    while (Me.Location.Distance(new WoWPoint(-4611.241, 3974.056, -71.84396)) > 1)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-4611.241, 3974.056, -71.84396));
                        Thread.Sleep(250);
                    }
                    while (Me.Location.Distance(new WoWPoint(-4608.253, 3969.863, -76.81166)) > 0.5)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-4608.253, 3969.863, -76.81166));
                        Thread.Sleep(250);
                    }
                    while (Me.Location.Distance(new WoWPoint(-4598.911, 3955.826, -77.3313)) > 0.5)
                    {
                        WoWMovement.ClickToMove(new WoWPoint(-4598.911, 3955.826, -77.3313));
                        Thread.Sleep(250);
                    }
                } 
            }
            DidUsePortal = false;
            PulseChanger();
            return;
        }

        // Math.Round((DateTime.Now - _TotalStartTime).TotalHours, 1), Math.Round((DateTime.Now - _TotalStartTime).TotalMinutes, 1))
        public static void TotalRunningTime()
        {
            Log(string.Format("Total Time Since Start: {0}", (DateTime.Now - _TotalStartTime).ToString()));
        }

        public static void TotalBaseTime()
        {
            Log(string.Format("Total Time this Task:  {0}", (DateTime.Now - _BaseStartTime).ToString()));
        }

        readonly Random _rnd = new Random();
        public int RanNum(int min, int max)
        {
            return _rnd.Next(min, max + 1);
        }

        public static void Log(string argument)
        {
            Logging.Write("[{0}] {1}", InternalName, argument);
        }

        public static void DebLog(string argument, params object[] args)
        {
            Logging.WriteDiagnostic("Diag: {0} {1}", argument, args);
        }

        public void Log(string argument, string target)
        {
            Logging.Write("[{0}] {1} {2}", Name, argument, target);
        }

        public WoWItem ItemCheck(uint _Entry)
        {
            WoWItem ReturnItem = null;
            foreach (WoWItem item in ObjectManager.GetObjectsOfType<WoWItem>().Where(o => o.BagSlot != 1 && o.Entry == _Entry))
            {
                ReturnItem = item;
            }
            return ReturnItem;
        }

        public WoWUnit UnitCheck(uint _Entry)
        {
            WoWUnit ReturnUnit = null;
            ObjectManager.Update();
            foreach (WoWUnit unit in ObjectManager.GetObjectsOfType<WoWUnit>().Where(o => o.Entry == _Entry))
            {
                ReturnUnit = unit;
            }
            return ReturnUnit;
        }

        public WoWObject ObjectCheck(uint _Entry)
        {
            WoWObject ReturnObject = null;
            ObjectManager.Update();
            foreach (WoWObject obj in ObjectManager.GetObjectsOfType<WoWObject>().Where(o => o.Entry == _Entry))
            {
                ReturnObject = obj;
            }
            return ReturnObject;
        }

    }



    
    
    
}
